using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using GuavaData;

namespace GuavaLib
{
    public partial class GuavaViewer : Form
    {
        GQueryNode gq;
        int tabIndx = 0;
        int yCo = 40;
        static Panel pnlDesiredVal = new Panel();
        Size frmSize = new Size();
        Point okPoint = new Point();
        Point cancelPoint = new Point();
        List<object> pnlControls = new List<object>();
        Boolean IsValid = true;
        public GuavaViewer()
        {
            InitializeComponent();
        }

        public GuavaViewer(GQueryNode g)
            : this()
        {  
            // Initialize list
            if (g.g.GDomain != null)
            {
                foreach (ConditionType ct in Enum.GetValues(typeof(ConditionType)))
                {
                    if (Condition.NeedsOrderedForCond(ct))
                    {
                        if (!(g.g.GDomain.IsOrdered)) continue;
                    }
                    if (Condition.NeedsContainForCond(ct))
                    {
                        if (!(g.g.GDomain.CanContain)) continue;
                    }
                    this.cboCondition.Items.Add(ct);
                }
            }
            else this.cboCondition.Enabled = false;
            
            Type t = g.g.GetType();
            PropertyInfo[] properties = t.GetProperties();

            Condition c = g.gqCondition;

            //save off original form size and buttons location
            frmSize = this.Size;
            okPoint = this.btnOK.Location;
            cancelPoint = this.btnCancel.Location;
            foreach (PropertyInfo pi in properties)
            {
                if ((pi.Name.Equals("LType")) ||
                    (pi.Name.Equals("CType")) ||
                    (pi.Name.Equals("GComponents")) ||
                    (pi.Name.Equals("Item")))
                    continue;
                object t1 = pi.GetValue(g.g, null);

                Label lblLabel = new System.Windows.Forms.Label();
                lblLabel.Location = new System.Drawing.Point(this.lblCondition.Left, 9 + yCo);
                lblLabel.Size = this.lblCondition.Size;
                lblLabel.TabIndex = tabIndx++;
                lblLabel.Text = pi.Name.TrimStart('G');
                this.Controls.Add(lblLabel);

                GTextBox gtbText = new GuavaLib.GTextBox();
                gtbText.Location = new System.Drawing.Point(this.cboCondition.Left, 6 + yCo);
                gtbText.Size = new System.Drawing.Size(105, 20);
                gtbText.TabIndex = tabIndx++;

                if ((pi.Name.Equals("GType")) && (t1 == null))
                {
                    Type ti = g.g.ctl;
                    if (ti.BaseType.Name.Equals("GForm"))
                        gtbText.Text = ti.BaseType.FullName;
                    else
                        gtbText.Text = ti.ToString();
                }
                else if ((pi.Name.Equals("GDefault")) && (t1 == null))
                    gtbText.Text = g.g.GDefault;
                else if (t1 == null)
                    gtbText.Text = String.Empty;
                else if (t1 != null)
                    gtbText.Text = t1.ToString();
                gtbText.ReadOnly = true;
                this.Controls.Add(gtbText);
                yCo = yCo + 27;
            }
            gq = g;  // Save off query node
            // If condition is already set, load its settings
            if (c != null)
            {
                this.cboCondition.SelectedItem = c.CondType;
                List<object> ls = c.Args;
                for (int i = 0; i < ls.Count; i++)
                {
                    Control ccc = pnlDesiredVal.Controls[(2 * i) + 1] as Control;
                    
                    // Consider the special case of an annotated Guid
                    if (ccc is ComboBox)
                    {
                        ComboBox cb = ccc as ComboBox;
                        if ((cb.Items.Count > 0) && (cb.Items[0] is GuavaData.Domain.AnnotatedGuid))
                        {
                            // We have our special case
                            foreach (GuavaData.Domain.AnnotatedGuid ag in cb.Items)
                            {
                                if (ag.Object.ToString() == ls[i].ToString())
                                {
                                    // Found the item, so select it and move on
                                    cb.SelectedItem = ag;
                                    break;
                                }
                            }

                            continue;
                        }
                    }

                    // Otherwise, just set the text
                    ccc.Text = ls[i].ToString();
                }
            }
            else
            {
                if (this.cboCondition.Enabled) this.cboCondition.SelectedIndex = 0;
            }
            gq = g;  // Save off query node
        }

        private void AddControls(int numtxtb, List<object> enumlist)
        {
            this.Size = frmSize;
            this.btnOK.Location = okPoint;
            this.btnCancel.Location = cancelPoint;
            pnlDesiredVal.Location = new Point(5, 9 + yCo);
            pnlDesiredVal.Size = new Size(190, 0);
            pnlDesiredVal.BackColor = Color.YellowGreen;
            pnlDesiredVal.TabIndex = tabIndx++;
            this.Controls.Add(pnlDesiredVal);
            pnlDesiredVal.Controls.Clear();
            int pyCo = 0;

            for (int count = 0; count < numtxtb; count++)
            {
                pnlDesiredVal.Size = new Size(pnlDesiredVal.Size.Width, pnlDesiredVal.Size.Height + 30);
                this.Size = new Size(this.Size.Width, this.Size.Height + 30);
                this.btnOK.Location = new Point(this.btnOK.Location.X, this.btnOK.Location.Y + 30);
                this.btnCancel.Location = new Point(this.btnCancel.Location.X, this.btnCancel.Location.Y + 30);

                if ((pnlControls.Count == 0) || ((pnlControls.Count) / 2 < (count + 1)))
                {
                    Label lblVLabel = new Label();
                    if (pnlControls.Count != 0)
                        pyCo = (pnlControls[2 * count - 1] as Control).Location.Y + 22;
                    lblVLabel.Location = new Point(5, 9 + pyCo);
                    lblVLabel.Size = new Size(85, 13);
                    lblVLabel.TabIndex = tabIndx++;
                    lblVLabel.Text = "Desired Value" + (count + 1).ToString();
                    pnlControls.Add(lblVLabel);

                    if (this.gq.g.GDomain.ToString() == "DateTime")
                    {
                        DateTimePicker dtpValues = new DateTimePicker();
                        dtpValues.Location = new Point(90, 6 + pyCo);
                        dtpValues.Size = new Size(83, 20);
                        dtpValues.TabIndex = tabIndx++;
                        pnlControls.Add(dtpValues);
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count] as Label);
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count + 1] as DateTimePicker);
                    }
                    else if (enumlist == null || enumlist.Count == 0)
                    {
                        TextBox txtValues = new TextBox();
                        txtValues.Location = new Point(90, 6 + pyCo);
                        txtValues.Size = new Size(83, 20);
                        txtValues.TabIndex = tabIndx++;
                        pnlControls.Add(txtValues);
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count] as Label);
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count + 1] as TextBox);
                    }
                    else
                    {
                        ComboBox cboValues = new ComboBox();
                        cboValues.Location = new Point(90, 6 + pyCo);
                        cboValues.Size = new Size(83, 20);
                        cboValues.TabIndex = tabIndx++;
                        foreach (object o in enumlist)
                            cboValues.Items.Add(o);
                        cboValues.SelectedIndex = 0;
                        pnlControls.Add(cboValues);
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count] as Label);
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count + 1] as ComboBox);
                    }
                }
                else
                {
                    pnlDesiredVal.Controls.Add(pnlControls[2 * count] as Label);
                    if (this.gq.g.GDomain.ToString() == "DateTime")
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count + 1] as DateTimePicker);
                    else if (enumlist == null || enumlist.Count == 0)
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count + 1] as TextBox);
                    else
                        pnlDesiredVal.Controls.Add(pnlControls[2 * count + 1] as ComboBox);
                }
            }
        }
        private void btnOK_Click(object sender, EventArgs e)
        {
            
            List<object> validatedargs = new List<object>();
            IsValid = true;
            validatedargs=GetListofValues();
            if (IsValid)
            {
                this.gq.gqCondition
                    = Condition.NewCondition((ConditionType)cboCondition.SelectedItem,validatedargs);
                this.Close();
            }
        }
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void cboCondition_SelectedIndexChanged(object sender, EventArgs e)
        {         
            int numargs
                = Condition.NumArgsForCond((ConditionType)this.cboCondition.SelectedItem);
            List<object> enumvalues=new List<object>();
            if (this.gq.g.GDomain != null)
            {
                enumvalues = this.gq.g.GDomain.ListOutput();
            }
            this.AddControls(numargs,enumvalues);
        }
        private void GuavaViewer_FormClosing(object sender, CancelEventArgs e)
        {
            if (!(IsValid))
            {
                e.Cancel = true;
            }
        }
        private List<object> GetListofValues()
        {
            List<object> args = new List<object>();
            foreach (Control ctrl in pnlDesiredVal.Controls)
            {
                if (!(ctrl.GetType().Name.Equals("Label")))
                    if (this.gq.g.GDomain != null)
                    {
                        try
                        {
                            if ((ctrl is ComboBox) && ((ctrl as ComboBox).SelectedItem is GuavaData.Domain.AnnotatedGuid))
                                args.Add(this.gq.g.GDomain.ConvertString(((ctrl as ComboBox).SelectedItem as GuavaData.Domain.AnnotatedGuid).Object.ToString()));
                            else if (this.gq.g.GDomain.ToString() == "DateTime")
                                args.Add((ctrl as DateTimePicker).Value);
                            else
                                args.Add(this.gq.g.GDomain.ConvertString(ctrl.Text));
                        }
                        catch (Exception err)
                        {
                            IsValid = false;
                            MessageBox.Show(err.Message);
                        }
                    }
                    else
                        args.Add(ctrl.Text);
            }
          
            return args;
        }

    }
}